package com.syyo.admin.aspect;

import com.syyo.admin.domain.entity.SysRole;
import com.syyo.admin.mapper.SysDeptMapper;
import com.syyo.admin.mapper.SysRoleDeptMapper;
import com.syyo.admin.mapper.SysRoleMapper;
import com.syyo.admin.mapper.SysUserMapper;
import com.syyo.common.domain.ResultVo;
import com.syyo.common.enums.ResultEnum;
import com.syyo.common.utils.MyListUtils;
import com.syyo.common.utils.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 校验部门权限，部门id，一定要放在参数最后一位
 */
@Aspect
@Component
public class DataAuthorizeAspect {

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysRoleDeptMapper roleDeptMapper;
    /**
     * 配置切入点
     */
    @Pointcut("@annotation(com.syyo.common.anno.DataAuthorize)")
    public void logPointcut() {}


    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {

        //获取request
        String username = SecurityUtils.getUsername();

        // 根据名字去查角色
        List<SysRole> roles = roleMapper.getRoleByUserName(username);
        if (MyListUtils.isEmpty(roles)){
            // 没有配置角色，直接返回没权限
            return notAuth();
        }

        int lastScope = getLastScope(roles);
        Set<Integer> deptIdSet = new HashSet<>();
        if (lastScope == 1){
            // 全部，直接返回
            return pjp.proceed();
        }else if (lastScope == 2){
            // 自定义,获取角色关联的部门id
            for (SysRole role : roles) {
                List<Integer> list = roleDeptMapper.getDeptById(role.getRoleId());
                if (MyListUtils.isNotEmpty(list)){
                    deptIdSet.addAll(list);
                }
            }
        }else if (lastScope == 3){
            // 本部门及以下部门，获取部门和子部门id
            Integer deptId = userMapper.getDeptByName(username);
            deptIdSet.add(deptId);
            List<Integer> list2 = deptMapper.getChildren(deptId);
            if (MyListUtils.isNotEmpty(list2)){
                deptIdSet.addAll(list2);
            }

        }else if (lastScope == 4){
            // 本部门，获取部门id
            Integer deptId = userMapper.getDeptByName(username);
            deptIdSet.add(deptId);
        }

        Object[] args = pjp.getArgs();
        if (args != null && args.length > 0){
            Integer deptId = (Integer) args[args.length -1] ;
            if (!deptIdSet.contains(deptId)){
                return notAuth();
            }
        }

        return pjp.proceed();
    }

    /**
     * 根据多个角色的权限范围，取出最大的权限范围，1：全部，2：自定义，3：本部门及以下部门，4：本部门
     * @param roles
     * @return
     */
    private int getLastScope(List<SysRole> roles) {
        int compareScope = 99;// 初始比较值
        for (SysRole role : roles) {
            Integer dataScope = role.getDataScope();
            // 全部权限
            if (dataScope == 1) {
                compareScope = dataScope;
                break;
            } else if (dataScope == 2) {
                // 自定义
                if (compareScope > dataScope) {
                    compareScope = dataScope;
                }
            } else if (dataScope == 3) {
                // 本部门及以下部门
                if (compareScope > dataScope) {
                    compareScope = dataScope;
                }
            } else if (dataScope == 4) {
                // 本部门
                if (compareScope > dataScope) {
                    compareScope = dataScope;
                }
            }

        }
        return compareScope;
    }

    /**
     * 没有数据权限
     * @return
     */
    private ResultVo notAuth()  {
        ResultVo<Object> resultVo = new ResultVo<>();
        resultVo.setCode(ResultEnum.E_90006.getCode());
        resultVo.setMessage(ResultEnum.E_90006.getMessage());
        return resultVo;
    }
}
